﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.CSharp;

namespace LibraryEA
{
    public class Classe
    {

        public enum Tipo
        {
            BusinessEntity,
            DataContract,
            Model
        }


        public class Propriedade 
        {
            public string nome;
            public string tipo;
            public string notes;
            public string rulesets;
        }

        public class Atributo
        {
            public string nome;
            public string tipo;
            public string notes;
            
        }
        public class Metodo
        {
            public string nome;
            public string retorno;
            public string parametros;
            public string notes;
            public string scope;
            public string behavior;
        }

        public string nome;
        public string tipo;
        public string nome_namespace;
        public string metatype;

        private List<Propriedade> _propriedades = new List<Propriedade>();
        public List<Propriedade> propriedades
        {
            get { return _propriedades;}
            set { _propriedades = value; }
        }
        private List<Atributo> _atributos = new List<Atributo>();

        public List<Atributo> atributos
        {
            get { return _atributos; }
            set { _atributos = value; }
        }

        private List<Metodo> _metodos = new List<Metodo>();

        public List<Metodo> metodos
        {
            get { return _metodos; }
            set { _metodos = value; }
        }
        public List<string> errosPossiveis = new List<string>();

        //public List<Classe_Namespace> GerarClasse(string path, List<Classe> classes, List<Classe> servico, List<string> errosPossiveis, bool geraArquivo) 
        //{

        //    this.propriedades = propriedades.OrderBy(n => n.nome).ToList();
        //    this.atributos = atributos.OrderBy(n => n.nome).ToList();
        //    this.metodos = metodos.OrderBy(n => n.nome).ToList();


        //    List<Classe_Namespace> lista_classes_geradas = new List<Classe_Namespace>();

        //    if (tipo == "Model" || ((nome_namespace.IndexOf("Model")>=0) && tipo == "Parameter")) 
        //    {
        //        string classe = TemplateModel.template_Model;
        //        classe = classe.Replace("@@namespace", nome_namespace);
        //        classe = classe.Replace("@@nomeclasse", nome);
        //        classe = classe.Replace("@@parameters_construtor", TemplateModel.CriaParametrosConstrutor(propriedades));
        //        classe = classe.Replace("@@parameters_atribuicao", TemplateModel.CriaParametrosAtribuicao(propriedades));
        //        classe = classe.Replace("@@parameters_definicao", TemplateModel.CriaParametrosDefinicao(atributos));
        //        classe = classe.Replace("@@parameters_propriedades", TemplateModel.CriaParametrosPropriedades(propriedades,atributos, errosPossiveis, this.nome));

        //        //formatação do código fonte
        //        classe = FormataCodigo(classe);

        //        if (geraArquivo)
        //        {
        //            if (!System.IO.Directory.Exists(path + "\\UI\\Model\\"))
        //                System.IO.Directory.CreateDirectory(path + "\\UI\\Model\\");

        //            System.IO.FileStream stream = System.IO.File.Create(path + "\\UI\\Model\\" + nome + ".cs");
        //            stream.Close();
        //            stream.Dispose();
        //            System.IO.File.AppendAllText(path + "\\UI\\Model\\" + nome + ".cs", classe);
        //        }

        //        lista_classes_geradas.Add(new Classe_Namespace() { Key = nome_namespace + "->" + nome, ClasseGerada = classe, NomeClasse = nome, NomeNamespace = nome_namespace });
        //        errosPossiveis.AddRange(this.errosPossiveis);

                
                    
        //    }
        //    else if (tipo == "BusinessEntity" || ((nome_namespace.IndexOf("BusinessEntity") >= 0) && tipo == "Parameter")) 
        //    {
        //        string classe = TemplateBusinessEntity.template_Model;
        //        classe = classe.Replace("@@namespace", nome_namespace);
        //        classe = classe.Replace("@@nomeclasse", nome);
        //        classe = classe.Replace("@@parameters_construtor", TemplateBusinessEntity.CriaParametrosConstrutor(propriedades));
        //        classe = classe.Replace("@@parameters_atribuicao", TemplateBusinessEntity.CriaParametrosAtribuicao(propriedades));
        //        classe = classe.Replace("@@parameters_definicao", TemplateBusinessEntity.CriaParametrosDefinicao(atributos));
        //        classe = classe.Replace("@@parameters_propriedades", TemplateBusinessEntity.CriaParametrosPropriedades(propriedades, atributos, errosPossiveis, this.nome));

        //        //formatação do código fonte
        //        classe = FormataCodigo(classe);

        //        if (geraArquivo)
        //        {
        //            if (!System.IO.Directory.Exists(path + "\\Servicos\\BusinessEntity\\"))
        //                System.IO.Directory.CreateDirectory(path + "\\Servicos\\BusinessEntity\\");

        //            System.IO.FileStream stream = System.IO.File.Create(path + "\\Servicos\\BusinessEntity\\" + nome + ".cs");
        //            stream.Close();
        //            stream.Dispose();
        //            System.IO.File.AppendAllText(path + "\\Servicos\\BusinessEntity\\" + nome + ".cs", classe);
        //        }

        //        lista_classes_geradas.Add(new Classe_Namespace() { Key = nome_namespace + "->" + nome, ClasseGerada = classe, NomeClasse = nome, NomeNamespace = nome_namespace });
        //        errosPossiveis.AddRange(this.errosPossiveis);
        //    }

        //    else if (tipo == "DataContract")
        //    {
        //        string classe = TemplateDataContract.template_Model;
        //        classe = classe.Replace("@@namespace", nome_namespace);
        //        classe = classe.Replace("@@nomeclasse", nome);
        //        classe = classe.Replace("@@parameters_definicao", TemplateDataContract.CriaParametrosDefinicao(atributos));
        //        classe = classe.Replace("@@parameters_propriedades", TemplateDataContract.CriaParametrosPropriedades(propriedades, atributos, errosPossiveis, this.nome));

        //        //formatação do código fonte
        //        classe = FormataCodigo(classe);

        //        if (geraArquivo)
        //        {
        //            if (!System.IO.Directory.Exists(path + "\\Servicos\\Service\\DataContract\\"))
        //                System.IO.Directory.CreateDirectory(path + "\\Servicos\\Service\\DataContract\\");

        //            System.IO.FileStream stream = System.IO.File.Create(path + "\\Servicos\\Service\\DataContract\\" + nome + ".cs");
        //            stream.Close();
        //            stream.Dispose();
        //            System.IO.File.AppendAllText(path + "\\Servicos\\Service\\DataContract\\" + nome + ".cs", classe);
        //        }

        //        lista_classes_geradas.Add(new Classe_Namespace() { Key = nome_namespace + "->" + nome, ClasseGerada = classe, NomeClasse = nome, NomeNamespace = nome_namespace });
        //        errosPossiveis.AddRange(this.errosPossiveis);
        //    }

        //    else if (tipo == "BusinessLogic")
        //    {
        //        string classe = TemplateBusinessLogic.template_Model;
        //        classe = classe.Replace("@@namespace_logic", nome_namespace.Replace("BusinessLogic", "ResourceAccess"));
        //        classe = classe.Replace("@@namespace_entity", nome_namespace.Replace("BusinessLogic", "BusinessEntity"));
        //        classe = classe.Replace("@@namespace", nome_namespace);
        //        classe = classe.Replace("@@nomeclasse", nome);
        //        classe = classe.Replace("@@metodos", TemplateBusinessLogic.CriaParametrosMetodos(metodos));

        //        //formatação do código fonte
        //        classe = FormataCodigo(classe);

        //        if (geraArquivo)
        //        {
        //            if (!System.IO.Directory.Exists(path + "\\Servicos\\BusinessLogic\\"))
        //                System.IO.Directory.CreateDirectory(path + "\\Servicos\\BusinessLogic\\");

        //            System.IO.FileStream stream = System.IO.File.Create(path + "\\Servicos\\BusinessLogic\\" + nome + ".cs");
        //            stream.Close();
        //            stream.Dispose();
        //            System.IO.File.AppendAllText(path + "\\Servicos\\BusinessLogic\\" + nome + ".cs", classe);
        //        }

        //        lista_classes_geradas.Add(new Classe_Namespace() { Key = nome_namespace + "->" + nome, ClasseGerada = classe, NomeClasse = nome, NomeNamespace = nome_namespace });
        //        errosPossiveis.AddRange(this.errosPossiveis);
        //    }
        //    else if (tipo == "ResourceAccess")
        //    {
        //        string classe = TemplateResourceAccess.template_Model;
        //        classe = classe.Replace("@@namespace_entity", nome_namespace.Replace("ResourceAccess", "BusinessEntity"));
        //        classe = classe.Replace("@@namespace", nome_namespace);
        //        classe = classe.Replace("@@nomeclasse", nome);
        //        classe = classe.Replace("@@metodos", TemplateResourceAccess.CriaParametrosMetodos(metodos));

        //        //formatação do código fonte
        //        classe = FormataCodigo(classe);

        //        if (geraArquivo)
        //        {
        //            if (!System.IO.Directory.Exists(path + "\\Servicos\\ResourceAccess\\"))
        //                System.IO.Directory.CreateDirectory(path + "\\Servicos\\ResourceAccess\\");

        //            System.IO.FileStream stream = System.IO.File.Create(path + "\\Servicos\\ResourceAccess\\" + nome + ".cs");
        //            stream.Close();
        //            stream.Dispose();
        //            System.IO.File.AppendAllText(path + "\\Servicos\\ResourceAccess\\" + nome + ".cs", classe);
        //        }

        //        lista_classes_geradas.Add(new Classe_Namespace() { Key = nome_namespace + "->" + nome, ClasseGerada = classe, NomeClasse = nome, NomeNamespace = nome_namespace });
        //        errosPossiveis.AddRange(this.errosPossiveis);
        //    }

        //    else if (tipo == "ServiceImplementation")
        //    {
        //        string classe = TemplateServiceImplementation.template_Model;
        //        classe = classe.Replace("@@namespace_servicecontract", nome_namespace.Replace("ServiceImplementation", "ServiceContract"));
        //        classe = classe.Replace("@@namespace", nome_namespace);
        //        classe = classe.Replace("@@nomeclasse", nome);
        //        classe = classe.Replace("@@metodos", TemplateServiceImplementation.CriaParametrosMetodos(metodos));

        //        //formatação do código fonte
        //        classe = FormataCodigo(classe);

        //        if (geraArquivo)
        //        {
        //            if (!System.IO.Directory.Exists(path + "\\Servicos\\Service\\ServiceImplementation\\"))
        //                System.IO.Directory.CreateDirectory(path + "\\Servicos\\Service\\ServiceImplementation\\");

        //            System.IO.FileStream stream = System.IO.File.Create(path + "\\Servicos\\Service\\ServiceImplementation\\" + nome + ".cs");
        //            stream.Close();
        //            stream.Dispose();
        //            System.IO.File.AppendAllText(path + "\\Servicos\\Service\\ServiceImplementation\\" + nome + ".cs", classe);
        //        }

        //        lista_classes_geradas.Add(new Classe_Namespace() { Key = nome_namespace + "->" + nome, ClasseGerada = classe, NomeClasse = nome, NomeNamespace = nome_namespace });
        //        errosPossiveis.AddRange(this.errosPossiveis);
        //    }

        //    else if (tipo == "Translator")
        //    {
        //        string classe = TemplateTranslator.template_Model;



        //        string diretorio = string.Empty;
        //        if (nome_namespace.IndexOf("Communication") >= 0)
        //        {
        //            diretorio = path + "\\UI\\Communication\\Translator\\";
        //            if (nome_namespace.IndexOf("ModelToDataContract") >= 0)
        //                diretorio += "ModelToDataContract\\";
        //            else
        //                diretorio += "DataContractToModel\\";
        //        }
        //        else
        //        {
        //            diretorio = path + "\\Servicos\\Service\\ServiceImplementation\\Translator\\";
        //            if (nome_namespace.IndexOf("BusinessEntityToDataContract") >= 0)
        //                diretorio += "BusinessEntityToDataContract\\";
        //            else
        //                diretorio += "DataContractToBusinessEntity\\";
        //        }
        //        classe = classe.Replace("@@namespace", nome_namespace);
        //        classe = classe.Replace("@@nomeclasse", nome);
        //        classe = classe.Replace("@@metodos", TemplateTranslator.CriaParametrosMetodos(metodos, nome_namespace, classes, servico));

        //        string diretorioMais = string.Empty;

        //        //formatação do código fonte
        //        classe = FormataCodigo(classe);

        //        if (geraArquivo)
        //        {
        //            if (!System.IO.Directory.Exists(diretorio))
        //                System.IO.Directory.CreateDirectory(diretorio);


        //            System.IO.FileStream stream = System.IO.File.Create(diretorio + nome + ".cs");
        //            stream.Close();
        //            stream.Dispose();
        //            System.IO.File.AppendAllText(diretorio + nome + ".cs", classe);
        //        }


        //        lista_classes_geradas.Add(new Classe_Namespace() { Key = nome_namespace + "->" + nome, ClasseGerada = classe, NomeClasse = nome, NomeNamespace = nome_namespace });
        //        errosPossiveis.AddRange(this.errosPossiveis);
        //    }
        //    else if (tipo.ToLower() == "interface" || tipo.ToLower() == "servicecontract" || tipo.ToLower() == "viewinterface")
        //    {

        //        string diretorio = string.Empty;
        //        string template = string.Empty;
        //        bool Presenter = true;
        //        if (nome_namespace.IndexOf("UI") > 0)
        //        {
        //            template = TemplatePresenterInterface.template_Model;
        //            diretorio = path + "\\UI\\Presenter\\";
        //            Presenter = true;
        //        }
        //        else
        //        {
        //            template = TemplateServiceContract.template_Model;
        //            diretorio = path + "\\Servicos\\Service\\ServiceContract\\";
        //            Presenter = false;
        //        }


        //        string classe = template;
        //        classe = classe.Replace("@@namespace", nome_namespace);
        //        classe = classe.Replace("@@nomeclasse", nome);
        //        classe = classe.Replace("@@metodos", (Presenter) ? TemplatePresenterInterface.CriaParametrosMetodos(metodos) : TemplateServiceContract.CriaParametrosMetodos(metodos));

        //        //formatação do código fonte
        //        classe = FormataCodigo(classe);

        //        if (geraArquivo)
        //        {
        //            if (!System.IO.Directory.Exists(diretorio))
        //                System.IO.Directory.CreateDirectory(diretorio);

        //            System.IO.FileStream stream = System.IO.File.Create(diretorio + nome + ".cs");
        //            stream.Close();
        //            stream.Dispose();
        //            System.IO.File.AppendAllText(diretorio + nome + ".cs", classe);
        //        }

        //        lista_classes_geradas.Add(new Classe_Namespace() { Key = nome_namespace + "->" + nome, ClasseGerada = classe, NomeClasse = nome, NomeNamespace = nome_namespace });
        //        errosPossiveis.AddRange(this.errosPossiveis);
        //    }

        //    else if (tipo == "Communication")
        //    {
        //        string classe = TemplateCommunication.template_Model;
        //        classe = classe.Replace("@@namespace", nome_namespace);
        //        classe = classe.Replace("@@nomeclasse", nome);
        //        classe = classe.Replace("@@metodos", TemplateCommunication.CriaParametrosMetodos(metodos));

        //        if (geraArquivo)
        //        {
        //            if (!System.IO.Directory.Exists(path + "\\UI\\Communication\\"))
        //                System.IO.Directory.CreateDirectory(path + "\\UI\\Communication\\");

        //            System.IO.FileStream stream = System.IO.File.Create(path + "\\UI\\Communication\\" + nome + ".cs");
        //            stream.Close();
        //            stream.Dispose();
        //            System.IO.File.AppendAllText(path + "\\UI\\Communication\\" + nome + ".cs", classe);
        //        }

        //        lista_classes_geradas.Add(new Classe_Namespace() { Key = nome_namespace + "->" + nome, ClasseGerada = classe, NomeClasse = nome, NomeNamespace = nome_namespace });
        //        errosPossiveis.AddRange(this.errosPossiveis);
        //    }
        //    else if (tipo == "Presenter")
        //    {
        //        string classe = TemplatePresenter.template_Model;
        //        classe = classe.Replace("@@namespace", nome_namespace);
        //        classe = classe.Replace("@@nomeclasse", nome);
        //        classe = classe.Replace("@@metodos", TemplatePresenter.CriaParametrosMetodos(metodos));
        //        classe = classe.Replace("@@parameters_definicao", TemplatePresenter.CriaParametrosDefinicao(atributos));
        //        classe = classe.Replace("@@parameters_propriedades", TemplatePresenter.CriaParametrosPropriedades(propriedades, atributos));

        //        //formatação do código fonte
        //        classe = FormataCodigo(classe);

        //        if (geraArquivo)
        //        {
        //            if (!System.IO.Directory.Exists(path + "\\UI\\Presenter\\"))
        //                System.IO.Directory.CreateDirectory(path + "\\UI\\Presenter\\");

        //            System.IO.FileStream stream = System.IO.File.Create(path + "\\UI\\Presenter\\" + nome + ".cs");
        //            stream.Close();
        //            stream.Dispose();
        //            System.IO.File.AppendAllText(path + "\\UI\\Presenter\\" + nome + ".cs", classe);
        //        }

        //        lista_classes_geradas.Add(new Classe_Namespace() { Key = nome_namespace + "->" + nome, ClasseGerada = classe, NomeClasse = nome, NomeNamespace = nome_namespace });
        //        errosPossiveis.AddRange(this.errosPossiveis);
        //    }
        //    else if (tipo.ToLower() == "enum" || tipo.ToLower() == "enumeration")
        //    {

        //        string diretorio = string.Empty;
        //        string template = string.Empty;
        //        Tipo tipo_enum = Tipo.BusinessEntity;


        //        if (nome_namespace.IndexOf("BusinessEntity") >= 0) 
        //        {
        //            diretorio = path + "\\Servicos\\BusinessEntity\\Enum\\";
        //            template = TemplateEnum.template_BE;
        //            tipo_enum = Tipo.BusinessEntity;
        //        }
        //        else if (nome_namespace.IndexOf("DataContract") >= 0)
        //        {
        //            diretorio = path + "\\Servicos\\Service\\DataContract\\Enum\\";
        //            template = TemplateEnum.template_DC;
        //            tipo_enum = Tipo.DataContract;
        //        }
        //        else if (nome_namespace.IndexOf("Model") >= 0)
        //        {
        //            diretorio = path + "\\UI\\Model\\Enum\\";
        //            template = TemplateEnum.template_MD;
        //            tipo_enum = Tipo.Model;
        //        }

        //        string classe = template;

        //        classe = classe.Replace("@@namespace", nome_namespace);
        //        classe = classe.Replace("@@nomeclasse", nome);

        //        switch (tipo_enum)
        //        {
        //            case Tipo.BusinessEntity:
        //                classe = classe.Replace("@@parameters_propriedades", TemplateEnum.CriaParametrosPropriedadesBE(atributos));
        //                break;
        //            case Tipo.DataContract:
        //                classe = classe.Replace("@@parameters_propriedades", TemplateEnum.CriaParametrosPropriedadesDC(atributos));
        //                break;
        //            case Tipo.Model:
        //                classe = classe.Replace("@@parameters_propriedades", TemplateEnum.CriaParametrosPropriedadesMD(atributos));
        //                break;
        //            default:
        //                break;
        //        }      
          
        //        //formatação do código fonte
        //        classe = FormataCodigo(classe);


        //        if (geraArquivo)
        //        {
        //            if (!System.IO.Directory.Exists(diretorio))
        //                System.IO.Directory.CreateDirectory(diretorio);

        //            System.IO.FileStream stream = System.IO.File.Create(diretorio + nome + ".cs");
        //            stream.Close();
        //            stream.Dispose();
        //            System.IO.File.AppendAllText(diretorio + nome + ".cs", classe);
        //        }

        //        lista_classes_geradas.Add(new Classe_Namespace() { Key = nome_namespace + "->" + nome, ClasseGerada = classe, NomeClasse = nome, NomeNamespace = nome_namespace });
        //        errosPossiveis.AddRange(this.errosPossiveis);

        //    }


        //    return lista_classes_geradas;
        //}

        private string FormataCodigo(string classe)
        {
            string[] linhas = classe.Split(new string[]{Environment.NewLine}, StringSplitOptions.None);

            StringBuilder sb = new StringBuilder();

            int count_chaves = 0;
            //bool achouChave = false;
            foreach (string linha in linhas) 
            {
                string linha_temporaria = string.Empty;
                linha_temporaria = linha.Trim();

                if (linha.IndexOf("}") >= 0)
                    count_chaves--;
                
                linha_temporaria = ColocaTabs(linha_temporaria, count_chaves);

                if (linha.IndexOf("{") >= 0) 
                {
                    count_chaves++;
                }
                
                

                
                sb.AppendLine(linha_temporaria);
            }

            return sb.ToString();
        }

        private string ColocaTabs(string linha_temporaria, int count_chaves)
        {
            string linha = linha_temporaria;

            int i=0;
            while (i < count_chaves) 
            {
                linha = "\t" + linha;
                i++;
            }
            return linha;
        }



        internal static Classe RetornaClassePorNamespace(List<Classe> classes, string nome_namespace, string nome_classe, List<Classe> classesServico)
        {

            string nome_classe_temporaria = nome_classe;

            if (nome_classe_temporaria.IndexOf(':') > 0) 
                nome_classe_temporaria = nome_classe_temporaria.Substring(nome_classe_temporaria.IndexOf(':')+1).Trim();


            foreach (Classe classe in classes) 
            {
                if (classe.nome_namespace.ToLower().IndexOf(nome_classe_temporaria.ToLower().Substring(0, nome_classe_temporaria.ToLower().LastIndexOf("."))) >= 0)
                    if (classe.nome == nome_classe_temporaria.Substring(nome_classe_temporaria.LastIndexOf(".") + 1))
                        return classe;
            }

            if (classesServico != null)
            {
                foreach (Classe classe in classesServico)
                {
                    if (classe.nome_namespace.ToLower().IndexOf(nome_classe_temporaria.ToLower().Substring(0, nome_classe_temporaria.ToLower().LastIndexOf("."))) >= 0)
                        if (classe.nome == nome_classe_temporaria.Substring(nome_classe_temporaria.LastIndexOf(".") + 1))
                            return classe;
                }
            }

            

            return null;
        }
    }
}
